/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */

Ext.namespace("Org");


/**
 *	Survey edit panel.
 *
 * @param config the configuration.
 */
Org.SurveyEditorPanel = function(config) {
	Org.SurveyEditorPanel.superclass.constructor.call(this, config);
};

Ext.extend(Org.SurveyEditorPanel, Ext.Panel, {

	data: null,

	mainDataForm: null,

	questionsGrid: null,

	questionStore: null,

	QuestionRecord: null,

	unitCombo: null,

	unitStore: null,

	waitDlg: null,

	initComponent: function() {
		this.layout = 'border';

		var disableEdition = false;
		var lifecycleId = 1;

		if(this.data) {
			this.title = MSG['survey'] + ' ' + this.data.code;
			lifecycleId = this.data.lifecycle.id;
			if(lifecycleId > 1) {
				disableEdition = true;
			}
		} else {
			this.title =  MSG['survey.new'];
		}
		this.closable = true;
		this.autoShow = true;
		this.iconCls = 'icon-survey-edit';

		// Tools
		this.tools = [{
			id: 'close',
			handler: this.onClose,
			scope: this
		}];

		var theDate = new Date();

		// main data form
		this.mainDataForm = new Ext.FormPanel({
			region: 'west',
			split: true,
			collapsible: false,
			title:  MSG['survey.header'],
			width: 340,
			labelWidth: 120,
			bodyStyle:'padding: 5px',
			items: [{
				xtype: 'hidden',
				name: 'id',
				value: (this.data) ? this.data.id : 0
			},{
				xtype: 'textfield',
				name: 'code',
				fieldLabel: MSG['survey.code'],
				value: (this.data) ? this.data.code : '',
				allowBlank : false,
				vtype : 'surveyCode'
			}, {
				xtype: 'textfield',
				name: 'title',
				fieldLabel: MSG['survey.title'],
				maxLength: 60,
				value: (this.data) ? this.data.title : ''
			},	{
				xtype: 'textarea',
				name: 'description',
				width: 165,
				fieldLabel: MSG['survey.description'],
				maxLength: 200,
				value: (this.data) ? this.data.description : ''
			}, {
				xtype: 'datefield',
				name: 'startDate',
				allowBlank: false,
				fieldLabel: MSG['survey.start.date'],
				format: 'd/m/Y',
				value: (this.data) ? this.data.startDate: theDate
			}, {
				xtype: 'datefield',
				name: 'endDate',
				allowBlank: false,
				fieldLabel: MSG['survey.end.date'],
				format: 'd/m/Y',
				value: (this.data) ? this.data.endDate: theDate.add(Date.YEAR, 1)
			}, {
				xtype: 'datefield',
				name: 'archivedDate',
				allowBlank: false,
				fieldLabel: MSG['survey.archived.date'],
				format: 'd/m/Y',
				value: (this.data) ? this.data.archivedDate: theDate.add(Date.YEAR, 2)
			}],
			buttons: [{
				text: MSG['button.save'],
				iconCls: 'icon-disk',
				handler: this.onSaveHeader,
				scope: this,
				disabled: lifecycleId > 3
			}, {
				text: MSG['button.cancel'],
				iconCls: 'icon-cancel',
				handler: this.onCancel,
				scope: this
			}]
		});

		// Grid
		this.unitStore = new Ext.data.JsonStore({
			url: CONTEXT_PATH +'/secure/designer/unit/find.json',
			root: 'results',
			totalProperty: 'total',
			remoteSort: true,
			baseParams: { sort: ['code'], dir: ['asc'] },
			fields: ['id', 'code', 'description']
		});


		this.unitCombo = new Ext.form.ComboBox({
			store: this.unitStore,
			displayField: 'code',
			valueField: 'code',
			editable: false,
			loadingText: MSG['wait.message'],
			width: 100,
			pageSize: 100,
			hideTrigger: false,
			forceSelection : true,
			allowBlank : false,
			triggerAction: 'all',
			tpl: new Ext.XTemplate(
					'<tpl for="."><div class="search-item">',
					'<h3>{code}</h3>',
					'{code} - {name}',
					'<br/>{description}',
					'</div></tpl>'
					),
			itemSelector: 'div.search-item'
		});


		this.QuestionRecord = Ext.data.Record.create([
			{name: 'code'},
			{name: 'description'},
			{name: 'unit', convert: function(r) {
				return r.code;
			}}
		]);

		this.questionStore = new Ext.data.Store({
			proxy: new Ext.data.MemoryProxy([]),
			reader: new Ext.data.JsonReader({}, this.QuestionRecord),
			fields: ['code', 'description', 'unit']
		});

		this.questionsGrid = new Ext.grid.EditorGridPanel({
			title: MSG['survey.questions'],
			region: 'center',
			viewConfig: {
				emptyText: MSG['survey.questions.empty'],
				forceFit: true
			},
			cm: new Ext.grid.ColumnModel([{
				header: MSG['question.code'],
				dataIndex: 'code',
				width: 20,
				sortable: true,
				editor: new Ext.form.TextField({
					allowBlank: false,
					vtype : 'questionCode'
				}),
				renderer:Common.CellRenderer
			}, {
				header: MSG['question.description'],
				dataIndex: 'description',
				width: 200,
				sortable: true,
				editor: new Ext.form.TextField({
					allowBlank: false,
					maxLength: 2000
				}),
				renderer:Common.CellRenderer
			}, {
				header: MSG['question.unit'],
				dataIndex: 'unit',
				width: 200,
				sortable: true,
				allowBlank: false,
				editor: this.unitCombo
			}]),
			store: this.questionStore,
			clicksToEdit: 1,
			selModel: new Ext.grid.RowSelectionModel({singleSelect: false}),
			bbar: [' ', '-', ' ', {
				text: MSG['button.add'],
				iconCls: 'icon-add',
				handler: this.onAdd,
				scope: this,
				disabled: disableEdition
			}, ' ', '-', ' ', {
				text: MSG['button.remove'],
				iconCls: 'icon-remove',
				handler: this.onRemove,
				scope: this,
				disabled: disableEdition
			}, ' ', '-', ' ', {
				text: MSG['button.save'],
				iconCls: 'icon-disk',
				handler: this.onSave,
				scope: this,
				disabled: disableEdition
			}, ' ', '-', ' ', {
				text: MSG['button.cancel'],
				iconCls: 'icon-cancel',
				handler: this.onCancel,
				scope: this
			}]
		});

		this.items = [this.mainDataForm, this.questionsGrid];

		if(this.data) {
			this.questionStore.loadData(this.data.questions, false);
		}
		this.unitStore.load({
			params:{start:0,limit:100, sort: ['code'], dir: ['asc']}
		});
		this.questionsGrid.on("validateedit", this.validateEdit, this);

		Org.SurveyEditorPanel.superclass.initComponent.call(this);
	},

	onAdd: function() {
		if (this.validateEditorGridPanel(this.questionsGrid)) {
			this.questionsGrid.stopEditing();
			this.questionStore.add(new this.QuestionRecord({code: '', description: '', unit: ''}));
			this.questionsGrid.startEditing(this.questionStore.getCount()-1, 0);
		}else {
			notifyError( MSG['error'],  MSG['error.wrongData']);
		}
	},

	onRemove: function() {
		var selections = this.questionsGrid.selModel.getSelections();

		for(var i = 0; i < selections.length; ++i){
			this.questionStore.remove(selections[i]);
		}
	},

	onClose: function() {
		Main.app.addPanel(null);
	},

	onCancel: function() {
		Main.app.closePanel(this);
	},

	validateCell: function(cellName, cellValue, ref) {
		var valid = true;
		switch(cellName) {
			case 'code':
				valid = this.questionStore.queryBy(function(record){
					return record.get('code') == cellValue;
				}).getCount() == ref;
				break;
			case 'unit':
				valid = this.questionStore.queryBy(function(record){
					return record.get('unit') == cellValue;
				}).getCount() == ref;
				break;
			case 'description':
				break;
		}
		return valid;
	},

	validateEdit: function(e) {

		e.cancel = false;
		var valid = true;
		var inValidMsg = '';
		switch(e.field) {
			case 'code':
				if(!this.validateCell('code',e.value,0) && e.value != e.originalValue) {
					inValidMsg = MSG['question.code.duplicated'];
					valid = false;
				}
				break;
			case 'unit':
				if(!this.validateCell('unit',e.value,0) && e.value != e.originalValue) {
					inValidMsg = MSG['question.code.duplicated'];
					valid = false;
				}
				break;
			case 'description':
				break;
		}
		if (!valid) {
			notifyError( MSG['error'],  inValidMsg);
		}
		return !e.cancel;
	},

	setSurvey: function(data) {
		this.setTitle( MSG['survey'] + ' ' + data.code);
		this.mainDataForm.getForm().findField('id').setValue(data.id);
		this.questionStore.loadData(data.questions, false);
		this.data = data;
	},

	getLifecycle: function() {
		if(this.data) {
			return this.data.lifecycle.id;
		}
		return 1;
	},

	validateEditorGridPanel : function (grid){
		var valid = true;
		var rows = grid.store.data.length;
		var cols = grid.colModel.config.length;
		var row = 0;
		while (row < rows && valid){
			var record = grid.store.getAt(row);
			var col = 0;
			while (col < cols && valid) {
				var cellEditor = grid.colModel.getCellEditor(col, row);
				if (cellEditor != undefined) {
					var columnName = grid.colModel.getDataIndex(col);
					var columnValue = record.data[columnName];
					cellEditor.field.setValue(columnValue);
					valid = cellEditor.field.isValid() && this.validateCell(columnName,columnValue,1);

				}
				col++;
			}
			row++;
		}
		return valid;
	},

	onSave: function() {

		var valid = true;
		// Validate main form
		if(!this.mainDataForm.getForm().isValid()) {
			valid= false;
		}

		if (valid){
			valid = this.validateEditorGridPanel(this.questionsGrid);
			if (valid) {
				var survey = this.mainDataForm.getForm().getValues();
				survey.questions = [];
				for(var i = 0; i < this.questionStore.getCount(); ++i) {
					survey.questions.push(this.questionStore.getAt(i).data);
				}
				Ext.Ajax.request({
					waitTitle: MSG['wait.title'],
					waitMsg: MSG['wait.message'],
					url: CONTEXT_PATH + '/secure/designer/survey/update.json',
					params: {
						survey: Ext.util.JSON.encode(survey)
					},
					success: function(response){
						var jsonResponse = Ext.util.JSON.decode(response.responseText);
						if( jsonResponse.success ) {
							this.setSurvey(jsonResponse.data);
							notifySuccess( MSG['update'],  MSG['update.success']);
						} else {
							var error = (jsonResponse.errors) ? jsonResponse.errors : '';
							if(error.code) {
								error = error.code;
							}
							notifyError( MSG['error'], error);
						}
					},
					failure: function(/* response */) {
						notifyError( MSG['error'],  MSG['error.message']);
					},
					scope: this
				});
			} else {
				notifyError( MSG['error'],  MSG['error.inputData']);
			}
		}
	},

	onSaveHeader: function() {
		// Validate main form
		if(!this.mainDataForm.getForm().isValid()) {
			return;
		}

		var theLifecycle = this.getLifecycle();
		var survey = this.mainDataForm.getForm().getValues();

		var DATE_FORMAT = 'd/m/Y';
		var currentDate = new Date();
		var startDate = Date.parseDate(survey.startDate, DATE_FORMAT);
		var endDate = Date.parseDate(survey.endDate, DATE_FORMAT);
		var archivedDate = Date.parseDate(survey.archivedDate, DATE_FORMAT);

		// Validate dates
		var isValid = true;

		if(theLifecycle == 1 && startDate < currentDate) {
			isValid = false;
			this.mainDataForm.getForm().findField('startDate').markInvalid(MSG['survey.start.date.error']);
		}

		if(endDate < startDate) {
			isValid = false;
			this.mainDataForm.getForm().findField('endDate').markInvalid(MSG['survey.end.date.error']);
		}
		if(archivedDate < endDate) {
			isValid = false;
			this.mainDataForm.getForm().findField('archivedDate').markInvalid(MSG['survey.archived.date.error']);
		}

		if(!isValid) {
			return;
		}



		Ext.Ajax.request({
			waitTitle: MSG['wait.title'],
			waitMsg: MSG['wait.message'],
			url: CONTEXT_PATH + '/secure/designer/survey/update.json',
			params: {
				survey: Ext.util.JSON.encode(survey)
			},
			success: function(response){
				var jsonResponse = Ext.util.JSON.decode(response.responseText);
				if( jsonResponse.success ) {
					this.setSurvey(jsonResponse.data);
					notifySuccess( MSG['update'],  MSG['update.success']);
				} else {
					notifyError( MSG['error'], jsonResponse.errors.code);
				}
			},
			failure: function(/*response*/){
				notifyError( MSG['error'],  MSG['error.message']);
			},
			scope: this
		});
	}

});


/**
 * Qualification Checks Paths associated.
 *
 * @param config the configuration.
 */
Org.SurveyCheckDelete = function(config) {
	Org.SurveyCheckDelete.superclass.constructor.call(this, config);
};

Ext.extend(Org.SurveyCheckDelete, Ext.Window, {

	gridCheck: null,

	checkStore: null,

	waitDlg: null,

	data: null,

	searchPanel: null,

	initComponent: function() {
		Ext.apply(this, {
			layout: 'border',
			width: '70%',
			height: 400,
			renderTo: Ext.getBody(),
			modal: true,
			iconCls: 'icon-survey-find',
			title: MSG['question.checks'],
			bodyStyle:'padding:5px'
		});

		// Store
		this.checkStore = new Ext.data.JsonStore({
			root: 'results',
			fields:[
				{name: 'id', type: 'int'},
				{name: 'code', type: 'string'},
				{name: 'name', type: 'string'},
				{name: 'state', type: 'string'}
			],
			data: Ext.util.JSON.decode(this.data)
		});

		//Custom column plugin for checkcolumn
		var elementsCheckBox = new Ext.grid.CheckboxSelectionModel();

		// Grid
		this.gridCheck = new Ext.grid.GridPanel({
			region: 'center',
			viewConfig: {
				emptyText: MSG['pagination.empty'],
				forceFit: true
			},
			cm: new Ext.grid.ColumnModel([
				elementsCheckBox,
				{header: MSG['survey.id'], dataIndex: 'id', width: 20, sortable: true},
				{header: MSG['survey.code'], dataIndex: 'code', width: 20, sortable: true},
				{header: MSG['survey.name'], dataIndex: 'name', width: 70, sortable: true},
				{header: MSG['survey.lifecycle'], dataIndex: 'state', width: 20, sortable: true, renderer: function(record) {
					return MSG[record];
				}}
			]),
			sm: elementsCheckBox,
			store: this.checkStore,
			buttons: [{
				text: MSG['button.validate'],
				iconCls: 'icon-ok',
				handler: this.onRemoveSelected,
				scope: this
			}, {
				text: MSG['button.cancel'],
				iconCls: 'icon-cancel',
				handler: this.onClose,
				scope: this
			}]
		});


		this.gridCheck.getView().getRowClass = function(record/*, index*/){
			return (( (record.get('state') == 'survey.production') || (record.get('state') == 'survey.closed') ) ? 'red-row' : '');
		};

		this.gridCheck.selModel.on('beforerowselect', function(sm, rowIndex, keepExisting, record){
			if ( (record.get('state') == 'survey.production') || (record.get('state') == 'survey.closed') ){
				notifyError(MSG['error'], MSG['survey.delete.eror']);
				return false;
			}
		});

		this.items = [this.gridCheck];

		Org.SurveyCheckDelete.superclass.initComponent.call(this);
	},

	onRemoveSelected: function(){
		var selections = this.gridCheck.getSelectionModel().getSelections();
		if (selections.length > 0){
			var elements = [];
			for (var i=0; i<selections.length; i++){
				elements.push(selections[i].get('id'));
			}

			Ext.Ajax.request({
				waitTitle: MSG['wait.title'],
				waitMsg: MSG['wait.message'],
				url: CONTEXT_PATH + '/secure/designer/survey/delete.json',
				success: function(){
					notifySuccess(MSG['delete'], MSG['delete.success']);
				},
				failure: function(){
					notifyError(MSG['delete'], MSG['delete.error']);
				},
				params: { elements: elements }
			});
		};

		this.searchPanel.onReset();

		this.onClose();
	},

	onClose: function(){
		this.close();
	}

});




/**
 *	Survey search panel.
 *
 * @param config the configuration.
 */
Org.SurveySearchPanel = function(config) {
	Org.SurveySearchPanel.superclass.constructor.call(this, config);
};

Ext.extend(Org.SurveySearchPanel, Ext.Panel, {

	searchForm: null,

	waitDlg: null,

	resultsStore: null,

	pageToolbar: null,

	resultsGrid: null,


	initComponent: function() {
		this.layout = 'border';
		this.title = MSG['surveys'];
		this.closable = true;
		this.autoShow = true;
		this.iconCls = 'icon-survey-find';

		// Tools
		this.tools = [{
			id: 'close',
			handler: this.onClose,
			scope: this
		}];

		// Search form
		this.searchForm = new Ext.FormPanel({
			region: 'west',
			split: true,
			collapsible: true,
			title: MSG['surveys'],
			width: 340,
			labelWidth: 120,
			bodyStyle:'padding: 5px',
			items: [{
				xtype: 'textfield',
				name: 'code',
				fieldLabel: MSG['survey.code'],
				maxLength: 20
			}, {
				xtype: 'textfield',
				name: 'title',
				fieldLabel: MSG['survey.title'],
				maxLength: 60
			},{
				xtype: 'textarea',
				name: 'description',
				width: 165,
				fieldLabel: MSG['survey.description'],
				maxLength: 200
			}, {
				xtype: 'simplecombo',
				hiddenName: 'lifecycle',
				fieldLabel: MSG['survey.lifecycle'],
				data: Common.SurveyLifecycles,
				width: 140
			}, {
				xtype: 'hidden',
				name: 'organization',
				value: Main.app.getUser().organization.id
			}],
			buttons: [{
				text: MSG['button.search'],
				iconCls: 'icon-search',
				handler: this.onSearch,
				scope: this
			}, {
				text: MSG['button.reset'],
				iconCls: 'icon-cancel',
				handler: this.onReset,
				scope: this
			}]
		});

		// Store
		this.resultsStore = new Ext.data.JsonStore({
			url: CONTEXT_PATH + '/secure/designer/survey/find.json',
			root: 'results',
			totalProperty: 'total',
			remoteSort: true,
			fields: ['id', 'code', 'title', 'lifecycle', 'description', 'startDate', 'endDate', 'archivedDate']
		});
		this.resultsStore.on("beforeload",
				function() {
					this.waitDlg = Ext.Msg.wait(MSG['wait.title'], MSG['wait.text']);
					this.resultsStore.baseParams = this.searchForm.getForm().getRawValues();
				}, this);
		this.resultsStore.on("load",
				function() {
					if(this.waitDlg) {
						this.waitDlg.hide();
					}
				}, this);

		// Pagination toolbar
		this.pageToolbar = new Ext.PagingToolbar({
			store: this.resultsStore,
			displayInfo: true,
			pageSize: 100,
			plugins: [new Common.PageSizePlugin(MSG['page.size'])],
			items:[
				'-', {
					text: MSG['button.remove'],
					iconCls: 'icon-remove',
					handler: this.onCheckRemoveSelected,
					scope: this
				}
			]
		});

		// Grid
		this.resultsGrid = new Ext.grid.GridPanel({
			title: MSG['result.title'],
			region: 'center',
			viewConfig: {
				emptyText: MSG['pagination.empty'],
				forceFit: true
			},
			cm: new Ext.grid.ColumnModel([
				{header: MSG['survey.id'], dataIndex: 'id', width: 20, sortable: true},
				{header: MSG['survey.code'], dataIndex: 'code', width: 30, sortable: true},
				{header: MSG['survey.title'], dataIndex: 'title', width: 60, sortable: true},
				{header: MSG['survey.lifecycle'], dataIndex: 'lifecycle', width: 30, sortable: true, renderer: function(r) {
					return MSG[r.name];
				}},
				{header: MSG['survey.description'], dataIndex: 'description', width: 100, sortable: true},
				{header: MSG['survey.link'], dataIndex: 'id', width: 100, sortable: true, renderer: function(r) {
					var lnk = CONTEXT_PATH + "/survey.do?id=" + r;
					return '<a href="' + lnk + '">' + lnk + '</a>';
				}},
				{header: MSG['survey.start.date'], dataIndex: 'startDate', width: 60, sortable: true},
				{header: MSG['survey.end.date'], dataIndex: 'endDate', width: 60, sortable: true},
				{header: MSG['survey.archived.date'], dataIndex: 'archivedDate', width: 60, sortable: true}
			]),
			store: this.resultsStore,
			bbar: this.pageToolbar
		});


		this.items = [this.searchForm, this.resultsGrid];

		this.pageToolbar.doLoad(0);

		this.resultsGrid.on("rowdblclick", this.onSelected, this);
		this.resultsGrid.on("rowcontextmenu", this.onContextMenu, this);

		Org.SurveySearchPanel.superclass.initComponent.call(this);
	},

	onClose: function() {
		Main.app.addPanel(null);
	},

	onSearch: function() {
		this.pageToolbar.doLoad(0);
	},

	onReset: function() {
		this.searchForm.getForm().reset();
		this.pageToolbar.doLoad(0);
	},

	onSelected: function(grid, rowIndex/*, evt*/) {
		var record = grid.getStore().getAt(rowIndex);

		Ext.Ajax.request({
			waitTitle: MSG['wait.title'],
			waitMsg: MSG['wait.message'],
			url: CONTEXT_PATH + '/secure/designer/survey/get.json',
			params: {
				id: record.data.id
			},
			success: function(response){
				var survey = Ext.util.JSON.decode(response.responseText);
				var surveyEditorPanel = new Org.SurveyEditorPanel({ data: survey });
				Main.app.addPanel(surveyEditorPanel);
			},
			failure: function(/*response*/){
				notifyError( MSG['error'],  MSG['error.message']);
			},
			scope: this
		});
	},

	onContextMenu: function(grid, rowIndex, e) {
		var record = grid.getStore().getAt(rowIndex);
		if(e.stopPropagation) {
			e.stopPropagation();
		}

		var menu = new Ext.menu.Menu({
			items: [{
				text: MSG['button.copy'],
				iconCls: 'icon-surveys',
				handler: function() {
					this.onCopy(record.data);
				},
				scope: this
			}]
		});

		menu.showAt(e.getXY());
	},

	onCopy: function(data) {

		Ext.Ajax.request({
			waitTitle: MSG['wait.title'],
			waitMsg: MSG['wait.message'],
			url: CONTEXT_PATH + '/secure/designer/survey/copy.json',
			params: {
				id: data.id
			},
			success: function(response){
				var survey = Ext.util.JSON.decode(response.responseText);
				var surveyEditorPanel = new Org.SurveyEditorPanel({ data: survey });
				Main.app.addPanel(surveyEditorPanel);
			},
			failure: function(/*response*/){
				notifyError( MSG['error'],  MSG['error.message']);
			},
			scope: this
		});
	},

	onCheckRemoveSelected: function() {
		var selections = this.resultsGrid.getSelectionModel().getSelections();
		if (selections.length > 0){
			var elements = [];
			for (var i=0; i<selections.length; i++){
				elements.push(selections[i].get('id'));
			}

			Ext.Ajax.request({
				url: CONTEXT_PATH + '/secure/designer/survey/checkdelete.json',
				success: function( result/*, request*/ ){
					if (result.responseText){
						var winCheck = new Org.SurveyCheckDelete({data: result.responseText, searchPanel: this});

						winCheck.show();
					}
				},
				failure: function(){
					notifyError(MSG['error'], MSG['check.error']);
				},
				params: { elements: elements },
				scope: this
			});
		}

	},

	getToolbar: function(){
		return this.pageToolbar;
	}

});


/**
 * Module definition.
 */
MODULES['5_surveys'] = {

	menu: null,

	init: function() {
		// Initialize common menu
		this.menu = new Ext.menu.Menu({
			items: [{
				text:  MSG['survey.new'],
				iconCls: 'icon-survey-add',
				handler: this.onNewSurvey,
				scope: this
			}, {
				text:  MSG['survey.search'],
				iconCls: 'icon-survey-find',
				handler: this.onSearchSurvey,
				scope: this
			}]
		});


		// Add menu to toolbar
		Main.app.mainToolbar.add({
			text:  MSG['surveys'],
			iconCls: 'icon-surveys',
			menu: this.menu
		});
	},


	onNewSurvey: function() {
		var surveyEditorPanel = new Org.SurveyEditorPanel();
		Main.app.addPanel(surveyEditorPanel);
	},
	onSearchSurvey: function() {
		var surveySearchPanel = new Org.SurveySearchPanel();
		Main.app.addPanel(surveySearchPanel);
	}

};